package com.hksj.drcs.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hksj.drcs.dto.create.CreateScheduleTaskDTO;
import com.hksj.drcs.dto.delete.DeleteScheduleTaskDTO;
import com.hksj.drcs.dto.update.UpdateScheduleTaskDTO;
import com.hksj.drcs.dto.update.UpdateScheduleTaskStatusDTO;
import com.hksj.drcs.entity.ScheduleTask;
import com.hksj.drcs.entity.ScheduleTaskLinkDevice;
import com.hksj.drcs.enums.EnableStatusEnum;
import com.hksj.drcs.enums.LoopTypeEnum;
import com.hksj.drcs.mapper.ScheduleTaskMapper;
import com.hksj.drcs.query.RemoteControlDeviceQuery;
import com.hksj.drcs.query.ScheduleTaskQuery;
import com.hksj.drcs.service.ScheduleTaskLinkDeviceService;
import com.hksj.drcs.service.ScheduleTaskService;
import com.hksj.drcs.vo.RemoteControlDeviceVO;
import com.hksj.drcs.vo.ScheduleTaskBaseInfoVO;
import com.hksj.drcs.vo.ScheduleTaskVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author zengke
 * @version 1.0
 * @see ScheduleTaskServiceImpl
 * @since 2025/05/22 10:35
 */

@Service(value = "scheduleTaskServiceImpl")
public class ScheduleTaskServiceImpl extends ServiceImpl<ScheduleTaskMapper, ScheduleTask> implements ScheduleTaskService {

    @Autowired
    @Qualifier(value = "scheduleTaskLinkDeviceServiceImpl")
    private ScheduleTaskLinkDeviceService scheduleTaskLinkDeviceService;

    /**
     * 创建定时任务
     *
     * @param dto 创建定时任务数据传输对象
     * @return 是/否创建成功
     */
    @Override
    public String createScheduleTask(CreateScheduleTaskDTO dto) {

        //验证参数
        Assert.notEmpty(dto.getDeviceModelIdList(),"请至少添加一个设备");

        //将dto转为entity
        ScheduleTask entity = Convert.convert(ScheduleTask.class, dto);

        //创建定时任务
        super.save(entity);

        //批量保存定时任务设备关联信息列表
        saveBatchScheduleTaskLinkDeviceList(dto.getDeviceModelIdList(), entity.getId());

        return "创建成功";
    }

    /**
     * 批量保存定时任务设备关联信息列表
     * @param deviceModelIdList 设备模型id列表
     * @param scheduleTaskId 定时任务id
     */
    private void saveBatchScheduleTaskLinkDeviceList(List<String> deviceModelIdList, String scheduleTaskId) {

        //构建定时任务设备关联信息列表
        List<ScheduleTaskLinkDevice> list = deviceModelIdList
                .stream()
                .map(deviceModelId -> {

                    //构建任务设备关联对象
                    ScheduleTaskLinkDevice scheduleTaskLinkDevice = new ScheduleTaskLinkDevice();
                    scheduleTaskLinkDevice.setDeviceModelId(deviceModelId);
                    scheduleTaskLinkDevice.setScheduleTaskId(scheduleTaskId);

                    //返回任务设备关联对象
                    return scheduleTaskLinkDevice;
                })
                .collect(Collectors.toList()); //收集任务设备关联列表

        //对任务设备关联表新增列表记录
        scheduleTaskLinkDeviceService.saveBatch(list);
    }

    /**
     * 通过定时任务id删除定时任务设备关联信息
     * @param scheduleTaskId
     */
    private void deleteScheduleTaskLinkDeviceByScheduleTaskId(String scheduleTaskId) {
        scheduleTaskLinkDeviceService.removeByMap(Collections.singletonMap("schedule_task_id", scheduleTaskId));
    }

    /**
     * 更新定时任务
     *
     * @param dto 更新定时任务数据传输对象
     * @return 是/否更新成功
     */
    @Override
    public String updateScheduleTask(UpdateScheduleTaskDTO dto) {

        //验证参数
        Assert.notEmpty(dto.getDeviceModelIdList(),"请至少选择一个设备");

        //查询当前定时任务
        ScheduleTask entity = super.getById(dto.getId());

        //判断定时任务是否存在
        if (ObjectUtils.isEmpty(entity)) {
            throw new RuntimeException("当前定时任务不存在或已删除");
        }

        //对当前定时任务进行更新
        //将dto转为entity
        ScheduleTask scheduleTask = Convert.convert(ScheduleTask.class, dto);

        //更新定时任务
        super.updateById(scheduleTask);

        //删除当前定时任务的 定时任务设备关联信息
        deleteScheduleTaskLinkDeviceByScheduleTaskId(dto.getId());

        //添加新的定时任务设备关联信息
        saveBatchScheduleTaskLinkDeviceList(dto.getDeviceModelIdList(), dto.getId());

        return "更新成功";
    }

    /**
     * 更新定时任务启用状态
     * @param dto 更新定时任务启用状态数据传输对象
     * @return 更新结果
     */
    public String updateScheduleTaskStatus(UpdateScheduleTaskStatusDTO dto){

        //查询当前定时任务
        ScheduleTask entity = super.getById(dto.getId());

        //判断定时任务是否存在
        if (ObjectUtils.isEmpty(entity)) {
            throw new RuntimeException("当前定时任务不存在或已删除");
        }

        //设置启用状态
        entity.setEnableStatus(dto.getStatus());

        //更新当前的定时任务
        super.updateById(entity);

        //启用结果
        String result = String.format("%s成功", EnableStatusEnum.getNameByCode(dto.getStatus()));

        //返回结果
        return result;
    }

    /**
     * 删除定时任务
     *
     * @param dto 删除定时任务数据传输对象
     * @return 是/否删除成功
     */
    @Override
    public String deleteScheduleTask(DeleteScheduleTaskDTO dto) {

        //查询当前定时任务
        ScheduleTask entity = super.getById(dto.getId());

        //判断定时任务是否存在
        if (ObjectUtils.isEmpty(entity)) {
            throw new RuntimeException("当前定时任务不存在或已删除");
        }

        //删除当前定时任务
        super.removeById(dto.getId());

        //删除当前定时任务的 定时任务设备关联信息
        deleteScheduleTaskLinkDeviceByScheduleTaskId(dto.getId());

        return "删除成功";
    }

    /**
     * 动态查询定时任务列表
     *
     * @param query 定时任务查询条件
     * @return 定时任务列表
     */
    @Override
    public List<ScheduleTaskVO> queryScheduleTaskList(ScheduleTaskQuery query) {

        return baseMapper.queryScheduleTaskListByPaging(null,query);
    }

    /**
     * 分页查询定时任务列表
     *
     * @param query 定时任务查询条件
     * @return 分页结果
     */
    @Override
    public IPage<ScheduleTaskVO> queryScheduleTaskListByPaging(ScheduleTaskQuery query) {

        //创建分页对象
        IPage<ScheduleTaskVO> page = new Page<>(query.getPageNum(), query.getPageSize());

        //进行分页查询
        List<ScheduleTaskVO> scheduleTaskList = baseMapper.queryScheduleTaskListByPaging(page, query);

        //设置分页结果
        page.setRecords(scheduleTaskList);

        //返回分页结果
        return page;
    }

    /**
     * 根据定时任务id查询定时任务基础信息
     *
     * @param id 定时任务id
     * @return 定时任务基础信息
     */
    @Override
    public ScheduleTaskBaseInfoVO queryScheduleTaskBaseInfo(String id) {

        //根据定时任务id查询定时任务基础信息
        ScheduleTask scheduleTask = super.getById(id);

        //判断定时任务是否存在
        if (!ObjectUtils.isEmpty(scheduleTask)) {

            //定时任务存在
            //构建定时任务基础信息
            ScheduleTaskBaseInfoVO baseInfoVO = Convert.convert(ScheduleTaskBaseInfoVO.class, scheduleTask);

            //根据定时任务id查询远程控制设备列表
            RemoteControlDeviceQuery query = new RemoteControlDeviceQuery();
            query.setScheduleTaskId(id);
            List<RemoteControlDeviceVO> remoteControlDeviceList = baseMapper.queryRemoteControlDeviceList(query);

            //设置远程控制设备列表
            baseInfoVO.setRemoteControlDeviceList(remoteControlDeviceList);

            //返回定时任务基础信息
            return baseInfoVO;
        }

        //若定时任务不存在
        return null;
    }

    /**
     * 查询远程集中控制设备树
     *
     * @param query 远程控制设备树查询条件
     * @return 远程控制设备树
     */
    @Override
    public List<RemoteControlDeviceVO> queryRemoteControlDeviceTree(RemoteControlDeviceQuery query) {

        //查询远程集中控制设备列表
        List<RemoteControlDeviceVO> remoteControlDeviceList = baseMapper.queryRemoteControlDeviceList(query);

//        //根据回路类型进行分组 得到远程控制设备集合
//        Map<Integer, List<RemoteControlDeviceVO>> remoteControlDeviceMap = remoteControlDeviceList.stream()
//                .collect(Collectors.groupingBy(RemoteControlDeviceVO::getLoopType));

        //根据设备类型分类
        Map<String, List<RemoteControlDeviceVO>> remoteControlDeviceMap = remoteControlDeviceList.stream()
                .collect(Collectors.groupingBy(RemoteControlDeviceVO::getDeviceCategoryCode));


        //遍历远程控制设备集合
        List<RemoteControlDeviceVO> treeList = remoteControlDeviceMap.entrySet().stream().map(entry -> {

            //entry的key就是当前的顶级节点
            //创建远程设备节点
            RemoteControlDeviceVO treeVO = new RemoteControlDeviceVO();

            //获取当前回路对应的远程设备列表的第一条
            List<RemoteControlDeviceVO> childList = entry.getValue();
            RemoteControlDeviceVO remoteControlDeviceVO = childList.get(0);

            //将位置信息设置到远程设备节点中
            treeVO.setDeviceModelName(remoteControlDeviceVO.getDeviceCategoryName());
            treeVO.setChildren(childList);
            treeVO.setBuildingId(remoteControlDeviceVO.getBuildingId());
            treeVO.setBuildingName(remoteControlDeviceVO.getBuildingName());
            treeVO.setFloorId(remoteControlDeviceVO.getFloorId());
            treeVO.setFloorName(remoteControlDeviceVO.getFloorName());

            //返回树节点
            return treeVO;
        }).collect(Collectors.toList());

        //返回树节点集合
        return treeList;
    }
}
